﻿//----------------------------------------------------------------
// Desc: 断言功能
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2010-06-11
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
// 本文件函数功能均可用于多线程
//   RELEASE 版需要断言功能时，在项目设置中添加 FASSERT_OPEN 预定义宏
//
// 使用方法(可组合)
//   FASSERT_STR    无条件直接断言，并抛出提示信息
//   FASSERT        条件断言，并抛出提示信息
//   FASSERT_LOG     打印一条提示信息到log文件
//   FAssertFmt     格式化字符串(注:不可嵌套使用)
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
//
//----------------------------------------------------------------
#if defined(_DEBUG) || defined(FASSERT_OPEN)

// 条件断言
// .exp 断言条件，如果不满足条件则抛出断言
// .msg 断言的详细说明
#define FASSERTW(exp, msg) ((exp) || (FAssertOutputStringW(_FFILEW_, _FLINEW_, _FTW(#exp), msg)))
#define FASSERTA(exp, msg) ((exp) || (FAssertOutputStringA(_FFILEA_, _FLINEA_, _FTA(#exp), msg)))
// 无条件，强制断言
// .msg 断言的详细说明
#define FASSERT_STRW(msg) FAssertOutputStringW(_FFILEW_, _FLINEW_, _FNILW, msg)
#define FASSERT_STRA(msg) FAssertOutputStringA(_FFILEA_, _FLINEA_, _FNILA, msg)

#else

#define FASSERTW(exp, msg) FNOOP
#define FASSERTA(exp, msg) FNOOP

#define FASSERT_STRW(msg) FAssertLogW(_FFILEW_, _FLINEW_, msg)
#define FASSERT_STRA(msg) FAssertLogA(_FFILEA_, _FLINEA_, msg)

#endif


// 不管DEBUG还是RELEASE版，强制条件断言
#define FASSERT_FORCEW(exp, msg) ((exp) || (FAssertOutputStringW(_FFILEW_, _FLINEW_, _FTW(#exp), msg)))
#define FASSERT_FORCEA(exp, msg) ((exp) || (FAssertOutputStringA(_FFILEA_, _FLINEA_, _FTA(#exp), msg)))

// 不管DEBUG还是RELEASE版，强制断言
#define FASSERT_STR_FORCEW(msg) FAssertOutputStringW(_FFILEW_, _FLINEW_, _FNILW, msg)
#define FASSERT_STR_FORCEA(msg) FAssertOutputStringA(_FFILEA_, _FLINEA_, _FNILA, msg)

// 输出到日志文件和控制台
#define FASSERT_LOGW(msg) FAssertLogW(_FFILEW_, _FLINEW_, msg)
#define FASSERT_LOGA(msg) FAssertLogA(_FFILEA_, _FLINEA_, msg)


//----------------------------------------------------------------
//
//----------------------------------------------------------------
// 初始化Assert设置（默认不需要初始化的）
// .out_file 日志输出文件,如果为0表示使用默认文件格式
extern FAPI void FAssertInitializeW(WCHAR* out_file = 0, DWORD out_flags = eAF_All);
extern FAPI void FAssertInitializeA(ACHAR* out_file = 0, DWORD out_flags = eAF_All);
// 输出一条断言内容（如果有输出到文件标记，每次打印都是一次IO操作）
// .file 抛出断言所在文件路径
// .line 抛出断言所在文件的号行
// .expression 通过断言必须满足的条件说明
// .message 此断言的详细说明
// .return 始终true
extern FAPI bool FAssertOutputStringW(const WCHAR* file, int line, const WCHAR* expression = (const WCHAR*)_FNILW, const WCHAR* message = (const WCHAR*)_FNILW);
extern FAPI bool FAssertOutputStringA(const ACHAR* file, int line, const ACHAR* expression = (const ACHAR*)_FNILA, const ACHAR* message = (const ACHAR*)_FNILA);
// 仅输出一条提示信息到log文件
// .message 信息内容
extern FAPI void FAssertLogW(const WCHAR* file, int line, const WCHAR* message);
extern FAPI void FAssertLogA(const ACHAR* file, int line, const ACHAR* message);
// 格式化字符串(注:不可嵌套使用，也不可以参数传给其它函数)
// .fmt 格式化标记字符串
// .... 参数列表
// .return 格式化完成后的字符串首地址
#if !(FUEL_OS_ANDROID)
extern FAPI const WCHAR* FCDECL FAssertFmtW(const WCHAR* fmt, ...);
#endif
extern FAPI const ACHAR* FCDECL FAssertFmtA(const ACHAR* fmt, ...);


#ifdef UNICODE
#define FAssertInitialize           FAssertInitializeW
#define FAssertOutputString         FAssertOutputStringW
#define FAssertLog                  FAssertLogW
#define FAssertFmt                  FAssertFmtW
#define FASSERT                     FASSERTW
#define FASSERT_STR                 FASSERT_STRW
#define FASSERT_FORCE               FASSERT_FORCEW
#define FASSERT_STR_FORCE           FASSERT_STR_FORCEW
#define FASSERT_LOG                 FASSERT_LOGW
#else
#define FAssertInitialize           FAssertInitializeA
#define FAssertOutputString         FAssertOutputStringA
#define FAssertLog                  FAssertLogA
#define FAssertFmt                  FAssertFmtA
#define FASSERT                     FASSERTA
#define FASSERT_STR                 FASSERT_STRA
#define FASSERT_FORCE               FASSERT_FORCEA
#define FASSERT_STR_FORCE           FASSERT_STR_FORCEA
#define FASSERT_LOG                 FASSERT_LOGA
#endif

#if FUEL_OS_WINDOWS
#define FFAssertInitialize          FAssertInitializeW
#define FFAssertOutputString        FAssertOutputStringW
#define FFAssertLog                 FAssertLogW
#define FFAssertFmt                 FAssertFmtW
#define FFASSERT                    FASSERTW
#define FFASSERT_STR                FASSERT_STRW
#define FFASSERT_FORCE              FASSERT_FORCEW
#define FFASSERT_STR_FORCE          FASSERT_STR_FORCEW
#define FFASSERT_LOG                FASSERT_LOGW
#else
#define FFAssertInitialize          FAssertInitializeA
#define FFAssertOutputString        FAssertOutputStringA
#define FFAssertLog                 FAssertLogA
#define FFAssertFmt                 FAssertFmtA
#define FFASSERT                    FASSERTA
#define FFASSERT_STR                FASSERT_STRA
#define FFASSERT_FORCE              FASSERT_FORCEA
#define FFASSERT_STR_FORCE          FASSERT_STR_FORCEA
#define FFASSERT_LOG                FASSERT_LOGA
#endif